package com.huayun.plugin.bk.service;

import org.springframework.stereotype.Service;

import java.io.*;
import java.nio.file.*;
import java.util.Arrays;
import java.util.List;

/**
 * XfoilEmbedded 服务类，用于运行 XFOIL 分析并生成极坐标数据。
 * 提供了两种运行模式：普通极坐标分析和压力系数分析。普通极坐标分析中也加入了压力系数分析脚本
 */
@Service
public class XfoilEmbedded {
    // 定义 XFOIL 工作目录路径
    private static final String WORK_DIR = System.getProperty("user.dir") + File.separator + "xfoil";

    // 定义 XFOIL 可执行文件路径
    private static final String XFOIL_EXE_PATH = WORK_DIR + File.separator + "xfoil.exe";

    // 定义 PXPlot 工具可执行文件路径（用于绘制极坐标图）
    private static final String PXPLOT_EXE_PATH = WORK_DIR + File.separator + "pxplot.exe";

    // 定义 PPlot 工具可执行文件路径（用于绘制压力系数图）
    private static final String PPLOT_EXE_PATH = WORK_DIR + File.separator + "pplot.exe";

    // 定义翼型数据文件路径
    private static final String DAT_FILE_PATH = WORK_DIR + File.separator + "mh.dat"; // 翼型数据文件路径

    // 定义 XFOIL 脚本文件路径
    private static final String COMMANDS_IN_PATH = WORK_DIR + File.separator + "commands.in";

    // 定义极坐标输出文件路径
    private static final String POLAR_PATH = WORK_DIR + File.separator + "polar.txt";

    // 定义标准输出文件路径
    private static final String OUT_PUT_PATH = WORK_DIR + File.separator + "outPut.txt";

    // 定义错误输出文件路径
    private static final String ERROR_PATH = WORK_DIR + File.separator + "error.txt";

    /**
     * 运行 XFOIL 极坐标分析。
     *
     * @param datName    翼型数据文件名
     * @param visc       黏性系数
     * @param startAngle 起始攻角
     * @param endAngle   结束攻角
     * @param stepAngle  攻角步长
     */
    public void run(String datName, double visc, double startAngle, double endAngle, double stepAngle) {
        try {
            // 1. 创建 xfoil 工作目录
            Files.createDirectories(Paths.get(WORK_DIR));

            // 2. 删除工作目录下指定名字的文件
            deleteSpecificFiles(WORK_DIR, Arrays.asList("polar.txt"));
            deleteSpecificFiles(WORK_DIR, Arrays.asList("outPut.txt"));

            // 3. 复制 XFOIL.exe 和相关工具到工作目录
            extractResource("/xfoil/xfoil.exe", XFOIL_EXE_PATH);
            extractResource("/xfoil/pxplot.exe", PXPLOT_EXE_PATH);
            extractResource("/xfoil/pplot.exe", PPLOT_EXE_PATH);

            // 4. 创建 XFOIL 脚本文件
            createXfoilScript(datName, visc, startAngle, endAngle, stepAngle);

            // 5. 运行 XFOIL 分析
            runXfoilAnalysis();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 运行 XFOIL 压力系数分析。
     *
     * @param datName    翼型数据文件名
     * @param visc       黏性系数
     * @param startAngle 起始攻角
     * @param endAngle   结束攻角
     */
    public void runCp(String datName, double visc, double startAngle, double endAngle) {
        try {
            // 1. 创建 xfoil 工作目录
            Files.createDirectories(Paths.get(WORK_DIR));

            // 2. 删除工作目录下指定名字的文件
            deleteSpecificFiles(WORK_DIR, Arrays.asList("cp.txt", "cp.png"));

            // 3. 复制 XFOIL.exe 和相关工具到工作目录
            extractResource("/xfoil/xfoil.exe", XFOIL_EXE_PATH);
            extractResource("/xfoil/pxplot.exe", PXPLOT_EXE_PATH);
            extractResource("/xfoil/pplot.exe", PPLOT_EXE_PATH);

            // 4. 创建 XFOIL 压力系数脚本文件
            createXfoilCpScript(datName, visc, startAngle, endAngle);

            // 5. 运行 XFOIL 分析
            runXfoilAnalysis();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除指定目录下指定名字的文件。
     *
     * @param directoryPath 目录路径
     * @param fileNames     文件名列表
     */
    private static void deleteSpecificFiles(String directoryPath, List<String> fileNames) {
        for (String fileName : fileNames) {
            Path filePath = Paths.get(directoryPath, fileName);
            if (Files.exists(filePath)) {
                try {
                    Files.delete(filePath);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 从资源目录提取文件到目标路径。
     *
     * @param resourcePath 资源路径
     * @param targetPath   目标路径
     * @throws IOException 如果文件复制失败
     */
    private static void extractResource(String resourcePath, String targetPath) throws IOException {
        if (!Files.exists(Paths.get(targetPath))) {
            try (InputStream is = XfoilEmbedded.class.getResourceAsStream(resourcePath)) {
                if (is == null) {
                    throw new FileNotFoundException("未找到资源文件: " + resourcePath);
                }
                Files.copy(is, Paths.get(targetPath), StandardCopyOption.REPLACE_EXISTING);
            }
        }
    }

    /**
     * 创建 XFOIL 极坐标分析脚本文件。
     *
     * @param datName    翼型数据文件名
     * @param visc       黏性系数
     * @param startAngle 起始攻角
     * @param endAngle   结束攻角
     * @param stepAngle  攻角步长
     * @throws IOException 如果文件写入失败
     */
    private static void createXfoilScript(String datName, double visc, double startAngle, double endAngle, double stepAngle) throws IOException {
        List<String> script = Arrays.asList(
                "LOAD " + datName,
                "OPER",
                "VISC " + visc,
                "PACC",
                "polar.txt",
                "",
                "ASEQ " + startAngle + " " + endAngle + " " + stepAngle,
                "PACC",
                "HARD",
                "ALFA " + (startAngle + endAngle) / 2,
                "CPWR cp.txt",
                "quit"
        );
        Files.write(Paths.get(COMMANDS_IN_PATH), script);
    }

    /**
     * 创建 XFOIL 压力系数分析脚本文件。
     *
     * @param datName    翼型数据文件名
     * @param visc       黏性系数
     * @param startAngle 起始攻角
     * @param endAngle   结束攻角
     * @throws IOException 如果文件写入失败
     */
    private static void createXfoilCpScript(String datName, double visc, double startAngle, double endAngle) throws IOException {
        List<String> script = Arrays.asList(
                "LOAD " + datName,
                "OPER",
                "ALFA " + (startAngle + endAngle) / 2,
                "CPWR cp.txt",
                "quit"
        );
        Files.write(Paths.get(COMMANDS_IN_PATH), script);
    }

    /**
     * 运行 XFOIL 分析。
     *
     * @throws IOException          如果文件操作失败
     * @throws InterruptedException 如果线程被中断
     */
    private static void runXfoilAnalysis() throws IOException, InterruptedException {
        ProcessBuilder pb = new ProcessBuilder(XFOIL_EXE_PATH);
        pb.directory(new File(WORK_DIR)); // 设置工作目录
        pb.redirectInput(new File(COMMANDS_IN_PATH));
        pb.redirectOutput(new File(OUT_PUT_PATH));
        pb.redirectError(new File(ERROR_PATH));
        Process p = pb.start();
        p.waitFor();
    }

    /**
     * 获取极坐标文件路径。
     *
     * @return 极坐标文件路径
     */
    public static String getPolarFilePath() {
        return POLAR_PATH;
    }


}
